/*
 * Copyright (c) 2023 Cshoo Org. All Rights Reserved.
 */

package org.cshoo.tattoo.authorize.app;

import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.cshoo.tattoo.authorize.api.dto.AddAppReq;
import org.cshoo.tattoo.authorize.api.dto.FrontPermissionResp;
import org.cshoo.tattoo.authorize.api.dto.UpdateAppReq;
import org.cshoo.tattoo.authorize.domain.bo.FrontPermissionBo;
import org.cshoo.tattoo.authorize.domain.po.App;
import org.cshoo.tattoo.authorize.domain.service.AppService;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayDeque;
import java.util.List;
import java.util.Objects;
import java.util.Queue;

/**
 * @author 杨翼
 * @since 1.0
 */
@Service
@Slf4j
public class AppAppService {

    @Resource
    private AppService appService;

    /**
     * 查询当前用户的前端权限信息
     * 包括菜单按钮
     *
     * @param appCode 编号
     * @return 权限信息
     */
    public List<FrontPermissionResp> queryCurrentUserFrontPermissionsTree(String appCode) {
        List<FrontPermissionResp> result = Lists.newArrayList();
        List<FrontPermissionBo> frontPermissions = appService.queryCurrentUserFrontPermissions(appCode);
        frontPermissions.forEach(fpb -> {
            FrontPermissionResp fpp = this.recursionBuildFrontPermissionResp(fpb);
            result.add(fpp);
        });
        return result;
    }

    /**
     * 查询当前用户的前端权限信息
     * 包括菜单按钮
     *
     * @param appCode 编号
     * @return 权限信息
     */
    public List<FrontPermissionResp> queryCurrentUserFrontPermissionsHash(String appCode) {
        List<FrontPermissionResp> result = Lists.newArrayList();
        List<FrontPermissionBo> frontPermissions = appService.queryCurrentUserFrontPermissions(appCode);
        Queue<FrontPermissionBo> queue = new ArrayDeque<>();
        frontPermissions.forEach(queue::offer);
        while (!queue.isEmpty()) {
            FrontPermissionBo frontPermissionBo = queue.poll();
            FrontPermissionResp fpp = new FrontPermissionResp();
            BeanUtils.copyProperties(frontPermissionBo, fpp, "children");
            result.add(fpp);
            List<FrontPermissionBo> children = frontPermissionBo.getChildren();
            if (CollectionUtils.isNotEmpty(children)) {
                children.forEach(queue::offer);
            }
        }
        return result;
    }

    /**
     * 判断此编号是否存在
     *
     * @param code app编号
     * @return 判断结果
     */
    public boolean checkAppCodeExists(String code) {
        return appService.checkAppCodeExists(code);
    }

    /**
     * 添加一个app
     *
     * @param addAppReq 添加app请求
     */
    public void addApp(AddAppReq addAppReq) {
        App app = new App();
        BeanUtils.copyProperties(addAppReq, app);
        appService.addApp(app);
    }

    /**
     * 修改app，这里修改app信息的name,uri,description字段
     *
     * @param updateAppReq 修改app请求对象
     */
    public void updateApp(UpdateAppReq updateAppReq) {
        App app = new App();
        BeanUtils.copyProperties(updateAppReq, app);
        appService.updateApp(app);
    }

    /**
     * 删除app
     *
     * @param id id
     */
    public void deleteApp(Long id) {
        appService.deleteApp(id);
    }

    /**
     * 查询app
     *
     * @return app列表
     */
    public List<App> findAllApp() {
        return appService.findAllApp();
    }

    /**
     * 使用递归的方法构造前端权限响应对象
     *
     * @param frontPermissionBo 前端权限bo对象
     * @return 前端权限响应对象
     */
    private FrontPermissionResp recursionBuildFrontPermissionResp(FrontPermissionBo frontPermissionBo) {
        if (Objects.isNull(frontPermissionBo)) {
            return null;
        }
        FrontPermissionResp fpr = new FrontPermissionResp();
        BeanUtils.copyProperties(frontPermissionBo, fpr, "children");
        if (CollectionUtils.isNotEmpty(frontPermissionBo.getChildren())) {
            List<FrontPermissionResp> children = Lists.newArrayList();
            frontPermissionBo.getChildren().forEach(chd -> children.add(recursionBuildFrontPermissionResp(chd)));
            fpr.setChildren(children);
        }
        return fpr;
    }
}
